package com.demo.springBoot2.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import cn.hutool.jwt.Claims;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.demo.springBoot2.entity.dto.UsersInfoLoginDTO;
import com.demo.springBoot2.entity.vo.UsersInfoLoginVO;
import com.demo.springBoot2.entity.vo.UsersInfoPhoneVO;
import com.demo.springBoot2.result.MyPage;
import com.demo.springBoot2.result.Result;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.demo.springBoot2.service.IUsersInfoService;
import com.demo.springBoot2.entity.UsersInfo;
import org.springframework.web.bind.annotation.RestController;

/**
 * <p>
 * 用户信息 前端控制器
 * </p>
 *
 * @author wuHua·pl
 * @since 2024-03-16
 */
@Slf4j
@Api(tags = "用户信息")
@RestController
@RequestMapping("/users-info")
public class UsersInfoController {

    @Resource
    private IUsersInfoService usersInfoService;

    @Autowired
    private RedisTemplate redisTemplate;
    /**
     * 密码进行加密和加盐
     */
    public static String generateSecureHash(String password, String salt) {
        //得到md5加密对象
        Digester md5 = new Digester(DigestAlgorithm.MD5);
        //（设置盐值）
        md5.setSalt(salt.getBytes());
        //digest 消化 Hex 16进制(对注册密码进行加密)
        String md5Pass = md5.digestHex(password);
        return md5Pass;
    }

    /**
     * 查询所有接口
     *
     * @return
     */
    @ApiOperationSupport(author = "wuHua·pl")
    @ApiOperation(value = "查询所有接口", protocols = "查询用户信息所有数据")
    @GetMapping
    public Result<List<UsersInfo>> findAll() {
        return Result.success(usersInfoService.list()).msg("查询所有成功");
    }

    /**
     * 根据id查询数据接口
     *
     * @param id
     * @return
     */
    @ApiOperationSupport(author = "wuHua·pl")
    @ApiOperation(value = "根据id查询数据接口", protocols = "通过组件id查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "组件id", required = true)
    })
    @GetMapping("/{id}")
    public Result<UsersInfo> findOne(@PathVariable Integer id) {
        return Result.success(usersInfoService.getById(id)).msg("根据ID查询成功");
    }

    /**
     * 分页查询接口
     *
     * @param pageNum
     * @param pageSize
     * @return
     */
    @ApiOperationSupport(author = "wuHua·pl")
    @ApiOperation(value = "分页查询接口", protocols = "分页查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "页码", example = "1", required = true),
            @ApiImplicitParam(name = "pageSize", value = "每页多少条", example = "10", required = true)
    })
    @GetMapping("/page")
    public Result<MyPage<UsersInfo>> findPage(@RequestParam Integer pageNum, @RequestParam Integer pageSize) {
        QueryWrapper<UsersInfo> queryWrapper = new QueryWrapper<>();
        return Result.success().data(usersInfoService.page(new Page<>(pageNum, pageSize), queryWrapper)).msg("分页查询成功");
    }

    /**
     * 新增接口
     *
     * @param
     * @return
     */
    @ApiOperationSupport(author = "wuHua·pl")
    @ApiOperation(value = "新增接口")
    @PostMapping("/add")
    public Result<String> add(UsersInfoPhoneVO usersInfoVO) {
        UsersInfo usersInfo = new UsersInfo();
        BeanUtil.copyProperties(usersInfoVO, usersInfo);
        String salt = IdUtil.simpleUUID().substring(0, 20);
        String password = generateSecureHash(usersInfo.getPassword(), salt);
        usersInfo.setPassword(password);
        usersInfo.setSalt(salt);
        usersInfo.setUsername("user-" + usersInfoVO.getPhone().substring(7, 11));
        usersInfoService.saveOrUpdate(usersInfo);
        return Result.success().msg("新增成功");
    }

    /**
     * 更新接口
     *
     * @param
     * @return
     */
    @ApiOperationSupport(author = "wuHua·pl")
    @ApiOperation(value = "更新接口")
    @PutMapping
    public Result<String> save(@RequestBody UsersInfo usersInfo) {
        usersInfoService.saveOrUpdate(usersInfo);
        return Result.success().msg("更新成功");
    }

    /**
     * 删除接口
     *
     * @param id
     * @return
     */
    @ApiOperationSupport(author = "wuHua·pl")
    @ApiOperation(value = "删除接口", protocols = "通过id删除")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "组件id", required = true)
    })
    @DeleteMapping("/{id}")
    public Result<String> delete(@PathVariable Integer id) {
        usersInfoService.removeById(id);
        return Result.success().msg("批量删除成功");
    }

    /**
     * 批量删除接口
     *
     * @param ids
     * @return
     */
    @ApiOperationSupport(author = "wuHua·pl")
    @ApiOperation(value = "批量删除接口", protocols = "批量删除接口")
    @PostMapping("/del/batch")
    public Result<String> deleteBatch(@RequestBody List<Integer> ids) {
        usersInfoService.removeByIds(ids);
        return Result.success();
    }

    @ApiOperation(value = "用户登录", protocols = "用户登录")
    @PostMapping("/login")
    public Result<Object> login(@Valid @RequestBody UsersInfoLoginVO usersInfoLoginVO) {
        UsersInfo usersInfo = new UsersInfo();
        BeanUtil.copyProperties(usersInfoLoginVO, usersInfo);
        UsersInfoLoginDTO login = usersInfoService.userLogin(usersInfo);

        //保存登录信息
        StpUtil.login(login.getUserId());
        //获取当前会话的token
        String tokenValue = StpUtil.getTokenValue();
        //设置token
        login.setToken(tokenValue);

        return Result.success(login).msg("登录成功");
    }

    /**
     * 根据手机号模糊查询用户
     *
     * @param phone
     * @return
     */
    @ApiOperationSupport(author = "Mr.Abel")
    @ApiOperation(value = "根据手机号模糊查询用户", protocols = "手机查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "电话号码", required = true)
    })
//    @SaCheckLogin
    @GetMapping("/getPhone/{phone}")
    public Result<List<UsersInfoLoginDTO>> getByPhone(@PathVariable String phone) {
        Integer userId = StpUtil.getLoginIdAsInt();
        List<UsersInfoLoginDTO> byPhone = usersInfoService.getUserByPhone(phone, userId);
        return Result.success(byPhone).msg("查询成功");
    }

    @ApiOperation(value = "个人信息")
    @SaCheckLogin
    @PostMapping("center")
    public Result<UsersInfoLoginDTO> getUserCenter() {
        //1、通过token获取id
        Integer id = StpUtil.getLoginIdAsInt();
        //2、得有一个key
        String key = "userinfo:"+id;
        //3、 key是否已经存在
        //4、 首先查询redis
        if(redisTemplate.hasKey(key)){
            log.info("从缓存中获取了用户");
            //5、直接查询redis
            return Result.success(redisTemplate.opsForValue().get(key));
        }
        log.info("从数据库中获取了用户");
        //6、通过id查询用户信息
        UsersInfoLoginDTO usersInfoLoginDTO = usersInfoService.getUserByUserId(id);
        //7、给redis一份
        redisTemplate.opsForValue().set(key,usersInfoLoginDTO);
        //8、返回
        return Result.success(usersInfoLoginDTO).msg("查询成功");
    }

    @ApiOperation(value = "好友信息")
    @PostMapping("userFriend")
    public Result<UsersInfoLoginDTO> getUserFriendCenter(Integer friendId) {
        UsersInfoLoginDTO usersInfoLoginDTO = usersInfoService.getUserByUserId(friendId);
        return Result.success(usersInfoLoginDTO).msg("查询成功");
    }
}